#include "ML307RDC_Module.h"

#include <string.h>
#include <time.h>
#include <stdio.h>
#include <cjson.h>

// 缓冲区地址。用来存放收发数据。存放在sdram3。无ECC
//接收缓冲区
/* 消息邮箱 */
struct rt_messagequeue mqtt_usart_tx_msq;
struct rt_messagequeue mqtt_usart_rx_msq;
struct rt_messagequeue mqtt_tx_msq;
struct rt_messagequeue mqtt_rx_msq;
struct rt_messagequeue mqtt_message_tx_msq;
struct rt_messagequeue mqtt_message_rx_msq;
/* 消息队列中用到的放置消息的内存池 */
__attribute__((at(0x20040000))) rt_uint8_t mqtt_usart_tx_msq_pool[16384];
__attribute__((at(0x20044000))) rt_uint8_t mqtt_usart_rx_msq_pool[16384];
__attribute__((at(0x20048000))) rt_uint8_t mqtt_tx_msq_pool[16384];
__attribute__((at(0x2004C000))) rt_uint8_t mqtt_rx_msq_pool[16384];
// mqtt缓冲区
__attribute__((at(0x20050000))) rt_uint8_t mqtt_message_rx_msq_pool[16384];
__attribute__((at(0x20054000))) rt_uint8_t mqtt_message_tx_msq_pool[16384];
// 收发缓冲区。存放在SDRAM4 ECC
__attribute__((at(0x20058000))) char mqtt_usart_rx_buf[1536];
__attribute__((at(0x20058600))) char mqtt_usart_tx_buf[1536];
__attribute__((at(0x20058C00))) char mqtt_rx_buf[1536];
__attribute__((at(0x20059200))) char mqtt_tx_buf[1536];
// mqtt收发缓冲区
__attribute__((at(0x20059800))) char mqtt_message_rx_buf[1536];
__attribute__((at(0x20059E00))) char mqtt_message_tx_buf[1536];
__attribute__((at(0x2005A400))) char mqtt_message_tx_build_buf[1536];

__attribute__((at(0x2005FFFF))) uint8_t lte_status;
__attribute__((at(0x2005FFFE))) uint8_t lte_connected;
__attribute__((at(0x2005FFFD))) uint8_t mqtt1_status;
__attribute__((at(0x2005FF7D))) char mqtt_client_id[128];
// netp状态。代表成功对时的次数。需要对时的时候会对这个清零。
// 次数主要是为了进行校正对时。需要多次对时消除误差
__attribute__((at(0x2005FF7C))) uint8_t sntp_ok;
__attribute__((at(0x2005FF7B))) uint8_t sntp_faild_times;
__attribute__((at(0x2005FF5B))) char time_block_buf[32];
/* 时间字符串缓存数组。分别是年月日时分秒星期时区。后俩其实没啥用 */
__attribute__((at(0x2005FF4B))) char time_str_buf[8][2];
__attribute__((at(0x2005FF43))) char time_date_buf[8];
__attribute__((at(0x2005FF42))) uint8_t mems_init_status;
__attribute__((at(0x2005FEC2))) char time_now_buf[128];
// 消息id，用来处理回复消息
uint32_t message_id;


// 创建用于串口发送的信号量
/* 创建一个动态信号量，初始值是 0 */
rt_sem_t mqtt_usart_tx_sem;

// 对时事件
struct rt_event sntp_event;


// ML307R任务
rt_thread_t lte_task_tid;
rt_thread_t lte_usart_tx_task_tid;
rt_thread_t lte_usart_rx_task_tid;

void Init_Lte(){
	// 初始化状态变量
	lte_status = RT_ERROR;
	lte_connected = RT_ERROR;
	mqtt1_status = 3;
	sntp_ok = 0;
	sntp_faild_times = 0;
	mems_init_status = 0;
	message_id = 0;
	
	{ // 初始化邮箱
		rt_mq_init(&mqtt_usart_tx_msq,
             "mqtt_usart_tx_msg",
             &mqtt_usart_tx_msq_pool[0],      /* 内存池指向 msg_pool */
             1536,              /* 每个消息的大小是 1 字节 */
             sizeof(mqtt_usart_tx_msq_pool),  /* 内存池的大小是 msg_pool 的大小 */
             RT_IPC_FLAG_PRIO); /* 如果有多个线程等待，优先级大小的方法分配消息 */
		rt_mq_init(&mqtt_usart_rx_msq,
             "mqtt_usart_rx_msg",
             &mqtt_usart_rx_msq_pool[0],      /* 内存池指向 msg_pool */
             1536,              /* 每个消息的大小是 1 字节 */
             sizeof(mqtt_usart_rx_msq_pool),  /* 内存池的大小是 msg_pool 的大小 */
             RT_IPC_FLAG_PRIO); /* 如果有多个线程等待，优先级大小的方法分配消息 */
						 
		rt_mq_init(&mqtt_rx_msq,
             "mqtt_rx_msg",
             &mqtt_rx_msq_pool[0],      /* 内存池指向 msg_pool */
             1536,              /* 每个消息的大小是 1 字节 */
             sizeof(mqtt_rx_msq_pool),  /* 内存池的大小是 msg_pool 的大小 */
             RT_IPC_FLAG_PRIO); /* 如果有多个线程等待，优先级大小的方法分配消息 */
		rt_mq_init(&mqtt_tx_msq,
             "mqtt_tx_msg",
             &mqtt_tx_msq_pool[0],      /* 内存池指向 msg_pool */
             1536,              /* 每个消息的大小是 1 字节 */
             sizeof(mqtt_tx_msq_pool),  /* 内存池的大小是 msg_pool 的大小 */
             RT_IPC_FLAG_PRIO); /* 如果有多个线程等待，优先级大小的方法分配消息 */
	} // 初始化邮箱
	
	{ // 初始化控制信号
		// 创建用于发送log的锁
		// 注意，sem不能在main函数被创建前创建。因为对象管理器还没被初始化。
		mqtt_usart_tx_sem = rt_sem_create("mqtt_usart_tx", 0, RT_IPC_FLAG_PRIO);
		if (mqtt_usart_tx_sem == RT_NULL) {
			for (;;) {
				GPIO_SetPins(LED_ERR_PORT, LED_ERR_PIN);
				DDL_DelayMS(100);
				GPIO_ResetPins(LED_ERR_PORT, LED_ERR_PIN);
				DDL_DelayMS(100);
			}
		}
	} // 初始化控制信号
	
	{ // 初始化事件集
		rt_event_init(&sntp_event, "sntp_event", RT_IPC_FLAG_PRIO);
	} // 初始化事件集
}

/** !\brief 4G发送线程
*
*/
void Thread_Mqtt_Usart_Send(void *parmameter){
	
	for (;;) { // 发送循环
    if (rt_mq_recv(&mqtt_usart_tx_msq, mqtt_usart_tx_buf, sizeof(mqtt_usart_tx_buf), RT_WAITING_FOREVER) > 0) {
      GPIO_SetPins(LED_ERR_PORT, LED_ERR_PIN);
    }
		
		{// LTE DMA发送
			led_busy_times = 4;
      DMA_SetSrcAddr(CM_DMA2, DMA_CH1, (uint32_t) mqtt_usart_tx_buf);

      DMA_SetTransCount(CM_DMA2, DMA_CH1, rt_strlen(mqtt_usart_tx_buf));

      (void) DMA_ChCmd(CM_DMA2, DMA_CH1, ENABLE);

      USART_FuncCmd(CM_USART1, USART_TX, ENABLE);
			rt_kprintf("success to send: %s\n", mqtt_usart_tx_buf);
      rt_err_t result = rt_sem_take(mqtt_usart_tx_sem, 500);
			
			if ( result != RT_EOK ){
				rt_kprintf("get a lte error by usart send thread task! code: %l\n", result);
			}
			
			SWDT_FeedDog();
    }// LTE DMA发送
		
	} // 发送循环
	
} // 4G发送线程

/** !\brief 4G接收线程
*
*/
void Thread_Mqtt_Usart_Recv(void *parmameter){
	
	for (;;) { // 接收循环
    if (rt_mq_recv(&mqtt_usart_rx_msq, mqtt_usart_rx_buf, sizeof(mqtt_usart_rx_buf), RT_WAITING_FOREVER) > 0) {
      GPIO_SetPins(LED_ERR_PORT, LED_ERR_PIN);
    } else {
			SWDT_FeedDog();
		}
		
		{// LTE DMA接收
			if (strlen(mqtt_usart_rx_buf) > 0 ) { // 检查是否为空消息
				rt_kprintf("lte get msg: %s", mqtt_usart_rx_buf);
				{ // 处理模块基本命令
					if (strstr(mqtt_usart_rx_buf, "+MATREADY") || (strstr(mqtt_usart_rx_buf, "OK") && lte_status != RT_EOK)){ // 上电模块状态
						// 这里模块要求驻网成功至少2秒才能够进行下一步操作
						if (lte_status != RT_EOK ){
							rt_thread_mdelay(2000);
						}
						
						lte_status = RT_EOK;
					} else if (strstr(mqtt_usart_rx_buf, "+MIPCALL: 1,1")) { // 驻网成功
						lte_connected = RT_EOK;
					} else if (strstr(mqtt_usart_rx_buf, "+MIPCALL: 0,1")) { // 驻网失效
						rt_thread_mdelay(100);
						rt_mq_send_wait(&mqtt_usart_tx_msq, "AT+MIPCALL=1,1\r", 1536, 500);
						lte_connected = RT_ERROR;
					} else if (strstr(mqtt_usart_rx_buf, "+MNTP: 0")) { // 接收到对时成功消息
						rt_kprintf("get time str\n");
						// 开始解析时间
						size_t buf_len = strlen(mqtt_usart_rx_buf);
						for (int index=0; index< buf_len; index++){
							if (mqtt_usart_rx_buf[index] == ','){ // 找到目标字符
								rt_kprintf("find str tip\n");
								if ( (index + 2) + 20 >= buf_len ){ // 确认是否包含有足够长的字符串
									rt_kprintf("error time str size\n");
									SWDT_FeedDog();
									continue;
								}// 确认是否包含有足够长的字符串
								
								{ // 开始处理时间字符串
									memset(time_block_buf, 0 ,32);
									memcpy(time_block_buf, mqtt_usart_rx_buf + index + 2, 20);
									sscanf(time_block_buf, "%hhu/%hhu/%hhu,%hhu:%hhu:%hhu+%hhu", time_date_buf,time_date_buf+1,time_date_buf+2,time_date_buf+3,time_date_buf+4,time_date_buf+5,time_date_buf+6);
									
									// 这里因为使用了四分之一时区。所以要除
									time_date_buf[6] /= 4;
									// 数值为从1900年到现在的时间。返回的年份只有两位数，因此100就是2000-1900。
									//time_date_buf[0] += 100;
								} // 开始处理时间字符串
								
								// 开始处理时间戳
//								struct tm Date;
//								Date.tm_year = time_date_buf[0];
//								Date.tm_mon = time_date_buf[1];
//								Date.tm_mday = time_date_buf[2];
//								Date.tm_hour = time_date_buf[3];
//								Date.tm_min = time_date_buf[4];
//								Date.tm_sec = time_date_buf[5];
								
								// rtc 时间结构体
								stc_rtc_time_t pstcRtcTime;
								pstcRtcTime.u8Hour = time_date_buf[3];
								pstcRtcTime.u8Minute = time_date_buf[4];
								pstcRtcTime.u8Second = time_date_buf[5];
								pstcRtcTime.u8AmPm = RTC_HOUR_24H;
								// 设置时间。RTC_DATA_FMT_DEC为10进制时间。RTC_DATA_FMT_BCD为BCD码时间
								//LL_PERIPH_WE(LL_PERIPH_ALL);
								RTC_SetTime(RTC_DATA_FMT_DEC, &pstcRtcTime);
								SWDT_FeedDog();
								
								// 设置日期
								stc_rtc_date_t pstcRtcDate;
								pstcRtcDate.u8Year = time_date_buf[0];
								pstcRtcDate.u8Month = time_date_buf[1];
								pstcRtcDate.u8Day = time_date_buf[2];
								//pstcRtcDate.u8Weekday = RTC_WEEKDAY_WEDNESDAY;
								RTC_SetDate(RTC_DATA_FMT_DEC, &pstcRtcDate);
								//LL_PERIPH_WP(LL_PERIPH_ALL);
								SWDT_FeedDog();
								rt_kprintf("set rtc successful %d\n", sntp_ok);
								// 释放NTP对时等候
//								rt_event_send(&sntp_event, NTP_FINISHED);
								if (sntp_ok <= 0) {
									sntp_ok = 2;
								} else {
									sntp_ok++;
								}
								rt_kprintf("set rtc successful %s\n", sntp_ok);
								sntp_faild_times = 0;
								SWDT_FeedDog();
							} // 找到目标字符
						}
					} else if (strstr(mqtt_usart_rx_buf, "+MQTTURC: \"conn\",0,0")) { // mqtt连接成功
						mqtt1_status = 0;
					} // 处理接收消息
					
					SWDT_FeedDog();
					continue;
				} // 处理模块基本命令
			}// 检查是否为空消息
			SWDT_FeedDog();
    }// LTE DMA接收
		
	} // 接收循环
	
} // 4G接收线程

void Run_Net_Task(){
	Init_Lte();
	
	{ // 初始化工作线程
		// 初始化lte发送线程
		lte_usart_tx_task_tid = rt_thread_create("Thread_Usart_Send",
														Thread_Mqtt_Usart_Send, RT_NULL,
														THREAD_STACK_SIZE,
														THREAD_PRIORITY, THREAD_TIMESLICE);

		if (lte_usart_tx_task_tid != RT_NULL) {
			rt_thread_startup(lte_usart_tx_task_tid);
		}
		
		// 初始化lte接收线程
		lte_usart_rx_task_tid = rt_thread_create("Thread_Usart_Send",
														Thread_Mqtt_Usart_Recv, RT_NULL,
														THREAD_STACK_SIZE,
														THREAD_PRIORITY, THREAD_TIMESLICE);

		if (lte_usart_rx_task_tid != RT_NULL) {
			rt_thread_startup(lte_usart_rx_task_tid);
		}
	} // 初始化工作线程
	SWDT_FeedDog();
	
	// 延迟2秒等待初始化完成
	rt_thread_mdelay(2000);
	
	for (;;){ // LTE主任务
		
		// 如果发现未初始化完成
		if (lte_status != RT_EOK){ // 检查模块是否能够响应
			rt_kprintf("try to init ML307R\n");
			rt_mq_send_wait(&mqtt_usart_tx_msq, "AT\r", 1536, 500);
			rt_thread_mdelay(2000);
			sntp_ok = 0;
			SWDT_FeedDog();
			continue;
		} else if (lte_connected != RT_EOK) { // 检查是否联网结束
			rt_kprintf("ML307R try to connected\n");
			rt_mq_send_wait(&mqtt_usart_tx_msq, "AT+MIPCALL?\r", 1536, 500);
			rt_thread_mdelay(2000);
			SWDT_FeedDog();
			sntp_ok = 0;
			continue;
		} else if (sntp_ok <= 0) { // ntp对时失效
			rt_mq_send_wait(&mqtt_usart_tx_msq, "AT+MNTP\r", 1536, 500);
			sntp_faild_times++;
			// 等待对时结束
//			rt_uint32_t e;
//			if (rt_event_recv(&sntp_event, (NTP_FINISHED), RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 500, &e) == RT_EOK)
//			{
//				sntp_faild_times = 0;
//				
//				// sntp_ok 1是未能成功但是暂时放过。从2开始是第几次有效连续对时，用来校正时间误差。
//				if (sntp_ok <= 0) {
//					sntp_ok = 2;
//				} else {
//					sntp_ok++;
//				}
//				
//        rt_kprintf("SNTP EVENT finished 0x%x\n", e);
//			} else { // 处理sntp对时失败
//				rt_kprintf("sntp failed\n");
//				if (sntp_faild_times >= 3) {
//					// 暂时没办法，只能先继续放过
//					sntp_ok = 1;
//				}
//				sntp_faild_times++;
//			} // 处理对时结束
			rt_thread_mdelay(5000);
			SWDT_FeedDog();
			continue;
		} else if (mqtt1_status != 0) { // 初始化mqtt
			rt_kprintf("MQTT try to connected\n");
			rt_mq_send_wait(&mqtt_usart_tx_msq, "AT+MQTTCFG=\"version\",4\r", 1536, 500);
			rt_thread_mdelay(200);
			rt_mq_send_wait(&mqtt_usart_tx_msq, "AT+MQTTCFG=\"keepalive\",120\r", 1536, 500);
			rt_thread_mdelay(200);
			rt_mq_send_wait(&mqtt_usart_tx_msq, "AT+MQTTCONN=0,\"39.102.213.211\",1883,\"12345678\",\"ioufev\",\"ioufev\"\r", 1536, 500);
			rt_thread_mdelay(2000);
			SWDT_FeedDog();
			continue;
		}// 如果发现未初始化完成
			
		{ // 循环主任务
			// rtc测试。只有需要测试rtc的时候才解开这个任务
//			if ( sntp_ok >0 ){
//				// 获取时间
//				stc_rtc_date_t pstcRtcDate;
//				RTC_GetDate(RTC_DATA_FMT_DEC, &pstcRtcDate);
//				stc_rtc_time_t pstcRtcTime;
//				RTC_GetTime(RTC_DATA_FMT_DEC, &pstcRtcTime);
//				rt_kprintf("get rtc time: 20%.02d-%.02d-%.02d-%.02dT%.02d:%.02d:%.02d+0800\n", 
//				pstcRtcDate.u8Year, pstcRtcDate.u8Month, pstcRtcDate.u8Day, pstcRtcDate.u8Weekday,
//				pstcRtcTime.u8Hour, pstcRtcTime.u8Minute, pstcRtcTime.u8Second);
//				
//				// 开始处理时间戳
//				struct tm Date;
//				time_t timestamp;
//				Date.tm_year = pstcRtcDate.u8Year + 100;
//				Date.tm_mon = pstcRtcDate.u8Month-1;
//				Date.tm_mday = pstcRtcDate.u8Day;
//				Date.tm_hour = pstcRtcTime.u8Hour;
//				Date.tm_min = pstcRtcTime.u8Minute;
//				Date.tm_sec = pstcRtcTime.u8Second;
//				
//				timestamp = mktime(&Date) + 8*3600;
//				struct tm* newDate = localtime(&timestamp);
//				strftime(time_now_buf, sizeof(time_now_buf), "%Y-%m-%d-%wT%d:%M:%S", newDate);
//				rt_kprintf("utc_8 time: %s\n", time_now_buf);
//				
//			}
			
			 // mqtt发送任务。等候100ms内的任务。如果没等到就循环一轮回来再说
			 if (rt_mq_recv(&mqtt_usart_rx_msq, mqtt_usart_rx_buf, sizeof(mqtt_usart_rx_buf), 100) > 0) {
				GPIO_SetPins(LED_ERR_PORT, LED_ERR_PIN);
			 } else {
				 /**
				 * received topic=$sys/cu1vj95wvfhbn8tr/0G9gAJ1IcdIpOWA/property/batch_reply, qos=0, payload={"code":"000000","message":"Success","messageId":"1"}
				 * publish topic=$sys/cu1vj95wvfhbn8tr/0G9gAJ1IcdIpOWA/property/batch, qos=1, payload={"messageId":"1","params":{"data":[{"value":"12","key":"temperature"},{"value":"1234.54","key":"longitude"},{"value":"2342.15","key":"latitude"},{"value":"30","key":"altitude"},{"value":"20","key":"humidity"}]}}
				 */
				 sprintf(mqtt_message_tx_build_buf, "AT+MQTTPUB=0,\"%s\",0,0,0,0,\"%s\"\r", "$sys/cu1vj95wvfhbn8tr/0G9gAJ1IcdIpOWA/property/batch", mqtt_usart_rx_buf);
				 rt_mq_send_wait(&mqtt_usart_tx_msq, mqtt_message_tx_build_buf, 1536, 500);
			 }
		} // 循环主任务

		rt_thread_mdelay(1000);
		SWDT_FeedDog();
	}// LTE主任务
}
